package connections;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.StreamConnection;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class BT2Web extends MIDlet implements CommandListener {

	
	//Change this
	String WEB_ADDRESS = "http://itp.nyu.edu/~dbo3/postNWrite.php";

	//Change this to the hardware address of your bluetooth device (leave out the colons or dashes).
	String BT_ADDRESS = "00A096179A85";
	
	//Char from bt that signifies end of transmission from BT
	char TERMINATION_CHAR = 10;
	
	//Char from bt that triggers a BT Transmission
	char REQUEST_CHAR = 65;
	
	//screen for the midlet interface
	Form mainForm;


	//bluetooth connection object using class below
	BTConnection myBTConnection;
	
	//for collecting data between web uploads
//	byte[] data = new byte[0];
	
	Vector data = new Vector();
	int numberOfInputBytes = 0;
	
	int num;
	
	TextField btTextField;
	TextField webTextField;
	TextField btAddressField ;
	TextField webAddressField ;



	protected void startApp() throws MIDletStateChangeException {
		//screen for the midlet
		mainForm = new Form("BT2WEB");
		//have the midlet display this screen
		//add a textfield
		btAddressField = new TextField("BT Hardware Address:", BT_ADDRESS, 12, TextField.ANY);
		webAddressField = new TextField("Web Address", WEB_ADDRESS, 50, TextField.ANY);
		//webAddressField = new TextField("Web Address", "http://itp.nyu.edu/~xxx/xxx.php", 50, TextField.ANY);
		btTextField = new TextField("From BT", "", 225, TextField.UNEDITABLE);
		webTextField = new TextField("From Web", "", 225, TextField.UNEDITABLE);
		mainForm.append(btAddressField);
		mainForm.append(webAddressField);
		mainForm.append(btTextField);
		mainForm.append(webTextField);
		//add some commands
		mainForm.addCommand(new Command("Connect BlueTooth", Command.OK, 1) );
		mainForm.addCommand(new Command("Disconnect BlueTooth", Command.OK, 2) );
		mainForm.addCommand(new Command("Send To Web", Command.OK, 3));
		mainForm.addCommand(new Command("Exit", Command.EXIT, 4));
		mainForm.setCommandListener(this);
		Display.getDisplay(this).setCurrent(mainForm);
		//make a connection using class below at specified address

	}
	
	public void commandAction(Command whichCommand, Displayable arg1) {
		if (whichCommand.getLabel().equals("Connect BlueTooth")){
			myBTConnection = new BTConnection(btAddressField.getString());
		}else if (whichCommand.getLabel().equals("Disconnect BlueTooth")){
			myBTConnection.disconnect();
		}else if (whichCommand.getLabel().equals("Send To Web")){
			sendToWeb();
		}else if (whichCommand.getLabel().equals("Exit")){
			try {
				destroyApp(false);
			} catch (MIDletStateChangeException e) {
				e.printStackTrace();
			}
			notifyDestroyed();
		}
	}
	
	/** Called from within the BTConnection when some bytes are available
	 * @param _input  new bytes
	 */
	void inputFromBT(byte[] _input) {
		data.addElement(_input);
		numberOfInputBytes = numberOfInputBytes + _input.length;
		if (_input[_input.length-1] == TERMINATION_CHAR ) {
			
			num++;
			//	this may give fragments of inputs instead of clean lines
			btTextField.setString(num + ": " + new String(_input));
			myBTConnection.send( REQUEST_CHAR);
		}
	}
	/**Called from within WebConnection when it uploads info and recieves confirmation
	 * @param _s  text of confirmation
	 */
	void sendToWeb(){
		byte[] dataArray = new byte[numberOfInputBytes];
		int dataArrayPosition =0;
		//turn the vector entries into one long array
		for (int i = 0; i < data.size(); i++){
			byte[] thisSegment = (byte[])  data.elementAt(i);
			System.arraycopy(thisSegment, 0, dataArray, dataArrayPosition, thisSegment.length);
			dataArrayPosition = dataArrayPosition + thisSegment.length;
		}
		webTextField.setString("Sending");
	
		new WebConnection(webAddressField.getString(), dataArray);
	
	}
	
	/**Called from within WebConnection when it uploads info and recieves confirmation
	 * @param _s  text of confirmation
	 */
	void responseFromWeb(String _s){
		webTextField.setString(	_s + " at: " +  new Date(System.currentTimeMillis()).toString());
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	

	//obligatory method of  MIDlet, close the bluetooth connection
	protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
		myBTConnection.disconnect();


		notifyDestroyed();
	}

	/**General Purpose method for reporting stuff
	 * @param _s  //text to report
	 */
	void put(String _s) {
		System.out.println(_s);
		mainForm.append(_s);
	}
	//obligatory method of MIDlet not used.
	protected void pauseApp() {

	}


	/**Creates a BlueTooth connection to a specified address, 
	 * listens for incoming bytes.
	 * @author Dano
	 */
	class BTConnection extends Thread {
		//url for connection
		String url;
		//regulates the listening thread
		boolean listening;
		//output stream for sending
		OutputStream os;
		

		BTConnection(String _address) {
			//surround the hardward address with necessary bluetooth stuff (:01 for serial)
			url = "btspp://" + _address + ":01;authenticate=false;encrypt=false;master=false";
			//call the run method in a thready kind of way.
			start();
		}

		/* Essence of the thread to watch for incoming bytes
		 * 
		 */
		public void run() {
			StreamConnection connection = null;
			InputStream is = null;
			listening = true;
			try {
				connection = (StreamConnection) Connector.open(url);
				try {
					is = connection.openInputStream();
					os = connection.openOutputStream();
					//send a byte out in case other side is waiting to be prompted
					send( REQUEST_CHAR); 
					while (listening) {
						//if bytes are ready 
						int available = is.available();
						if (available > 0) {
							byte[] input = new byte[available];
							is.read(input);
							//tell the midlet about it
							inputFromBT(input);
						}
					}
					is.close();
					os.close();
				} catch (IOException e) {
					listening = false;
					put("Problem Listening");
				}
			} catch (IOException e) {
				listening = false;
				put("Sorry but could not connect. to " + url);
			}

			try {
				connection.close();
			} catch (IOException e) {
				put("Trouble Closing Connection.");

			}

		}

		void send(int _output) {
			try {
				os.write((byte)_output);
				os.flush();
			} catch (IOException e) {
				put("Problem Sending");
			}
		}


		void disconnect() {
			listening = false;
		}

	}

	/**Makes a thread that looks after the sending to a web address and listening for a response.
	 * @author Dano
	 */
	class WebConnection extends Thread {
		/* The php code that this talks to
		 * <?
	$tmp = $_FILES['data_file']['tmp_name'];
	$size = filesize($tmp );
	$src = fopen($tmp, 'r');
	$content = fread($src,  $size);
	$dest = fopen("./up/postNWrite.txt", 'a') ;
	fwrite($dest,$content);
	fclose($dest);
	
	print "Wrote $size bytes to postNWrite.txt";
?>

		 */
		String url;
		byte[] dataToGo;

		WebConnection(String _address, byte[] _data) {
			//we are using the GET method so we will put the data on the url after the "?"
			url = _address ;
			dataToGo = _data;
			//put("url: " + url);
			start();
		}

		public void run() {
			HttpConnection connection = null;
			InputStream is = null;
			String response = "Server Response:";
			String extraInfo = "None";
			put("Sending " + dataToGo.length);
			try {
				connection = (HttpConnection) Connector.open(url);
				connection.setRequestMethod(HttpConnection.POST);
				//HttpConnection c = (HttpConnection) Connector.open(url);

				// /MAKE AND SEND A HEADER
				
			;
			
			connection.setRequestProperty("Content-Type", "multipart/form-data, boundary=AaB03x");
				DataOutputStream dataOut = new DataOutputStream(connection.openOutputStream());
				//String boundary = \r\n";
				dataOut.write(("--AaB03x\r\n").getBytes());
				dataOut.write(("Content-Disposition: form-data; name=\"data_file\"; filename=\"" + extraInfo + "\"\r\n").getBytes());
				dataOut.write(("Content-Type: " + "data/bytes" + " \r\n").getBytes());
		
				dataOut.write("\r\n".getBytes());

				// /SEND THE BODY
		
				dataOut.write(dataToGo, 0, dataToGo.length);

				// SEND THE END
				dataOut.write("\r\n--AaB03x--\r\n".getBytes());
				dataOut.flush();
				is = connection.openDataInputStream();
				int ch;
				while ((ch = is.read()) != -1) {
					response = response + (char) ch;
				}
				is.close();
				connection.close();
			} catch (Exception e) {
				put("Problem with get " + e);
			}
			//send the response back to the midlet
			responseFromWeb(response);

		}

	}

	

}
